package etc

import (
	"UserServer/rpc/internal/config"
	"context"
	"fmt"
	clientv3 "go.etcd.io/etcd/client/v3"
	"log"
	"os"
	"os/signal"
	"sync/atomic"
	"syscall"
	"time"
)

// 写一个服务注册,rpc 服务端口为127.0.0.1:50051

var (
	shutdownFlag int32 // 原子标记位用于优雅关闭控制
)

func RegisterEtcdService(etcd config.Etcd) {
	// 注册etcd服务
	etcdCli, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"localhost:2379"},
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer etcdCli.Close() // 确保关闭连接

	// etcd的键
	key := "/services/" + etcd.Name

	leaseID, err := registerWithRetry(etcdCli, key, etcd.Address, 3)
	if err != nil {
		log.Fatal("初始注册失败:", err)
	}

	// 心跳协程（带重试）
	// 信号处理 ， 用于捕获操作系统发送的信号
	sigCh := make(chan os.Signal, 1)
	// 将指定的信号（SIGINT 和 SIGTERM）绑定到通道 sigCh
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
	// 主循环
	for {
		select {
		case <-sigCh:
			atomic.StoreInt32(&shutdownFlag, 1)
			log.Println("接收到关闭信号，开始清理...")
			revokeAndDelete(etcdCli, key, leaseID)
			return
		case <-time.After(5 * time.Second):
			// 定期检查租约状态（生产环境可选）
		}
	}

}

// registerWithRetry 注册逻辑（自带重试）
// 参数介绍：参数是etcd的服务端+服务注册的key + 服务地址 + 重试次数
func registerWithRetry(cli *clientv3.Client, key, addr string, maxRetry int) (clientv3.LeaseID, error) {
	retryInterval := 1 * time.Second

	for i := 0; i < maxRetry; i++ {
		// 申请新租约
		leaseResp, err := cli.Grant(context.Background(), 15)
		if err != nil {
			log.Printf("租约申请失败(%d/%d): %v", i+1, maxRetry, err)
			time.Sleep(retryInterval)
			retryInterval *= 2 // 指数退避
			continue
		}

		// 注册服务
		if _, err = cli.Put(context.Background(), key, addr, clientv3.WithLease(leaseResp.ID)); err != nil {
			log.Printf("服务注册失败(%d/%d): %v", i+1, maxRetry, err)
			time.Sleep(retryInterval)
			retryInterval *= 2
			continue
		}
		fmt.Println("注册成功", leaseResp.ID)
		// 启动心跳协程
		go startKeepAlive(cli, leaseResp.ID, key, addr)

		//测试服务监听
		//time.Sleep(10 * time.Second)
		//NewLeaseResp, err := cli.Grant(context.Background(), 15)
		//if err != nil {
		//	log.Printf("租约申请失败(%d/%d): %v", i+1, maxRetry, err)
		//	time.Sleep(retryInterval)
		//	retryInterval *= 2 // 指数退避
		//	continue
		//}
		//if _, err = cli.Put(context.Background(), key, "127.0.0.1:50052", clientv3.WithLease(NewLeaseResp.ID)); err != nil {
		//	log.Printf("服务注册失败(%d/%d): %v", i+1, maxRetry, err)
		//	time.Sleep(retryInterval)
		//	retryInterval *= 2
		//	continue
		//}
		//fmt.Println(NewLeaseResp.ID)
		return leaseResp.ID, nil
	}
	return 0, fmt.Errorf("超过最大重试次数")
}

// 保持心跳
func startKeepAlive(cli *clientv3.Client, leaseID clientv3.LeaseID, key, addr string) {
	retryCount := 0
	maxRetry := 3
	keepAliveCh, err := cli.KeepAlive(context.Background(), leaseID)
	if err != nil {
		log.Printf("心跳初始化失败: %v", err)
		return
	}

	for {
		select {
		case kaResp, ok := <-keepAliveCh:
			if atomic.LoadInt32(&shutdownFlag) == 1 {
				return
			}

			if !ok {
				log.Println("心跳通道异常关闭")
				if retryCount >= maxRetry {
					log.Fatal("连续心跳失败，终止服务")
				}

				// 尝试重新注册
				newLeaseID, err := registerWithRetry(cli, key, addr, maxRetry)
				if err != nil {
					retryCount++
					time.Sleep(time.Duration(retryCount) * time.Second)
					continue
				}

				log.Printf("新租约 %x 注册成功，终止旧心跳协程", newLeaseID)
				return
			}

			retryCount = 0
			log.Printf("租约 %x 心跳成功, TTL: %d", kaResp.ID, kaResp.TTL)
		}
	}
}

// 清理注册信息
func revokeAndDelete(cli *clientv3.Client, key string, leaseID clientv3.LeaseID) {
	// 1. 撤销租约
	if _, err := cli.Revoke(context.Background(), leaseID); err != nil {
		log.Printf("租约撤销失败: %v", err)
	} else {
		log.Println("租约已撤销")
	}

	// 2. 删除键
	if _, err := cli.Delete(context.Background(), key); err != nil {
		log.Printf("键删除失败: %v", err)
	} else {
		log.Println("服务键已删除")
	}
}
